added 3dengfx into the repo, probably not the correct version for this
[summerhack] / src / 3dengfx / src / common / locator.c
1 /*
2 This is a small cross-platform resource file locator library.
3 Author: John Tsiombikas <nuclear@siggraph.org> 2004
4
5 This library is public domain, you are free to do whatever you like with it,
6 NO WARANTY whatsoever is provided with this library, use it at your own risk.
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include "locator.h"
13
14 #ifdef HAVE_CONFIG
15 #include "config.h"
16 #endif  /* HAVE_CONFIG */
17
18 #ifdef __unix__
19 #define __USE_BSD       /* to include readlink() prototype */
20 #include <unistd.h>
21
22 #define DIR_SEP         '/'
23 #define HOME_ENV        "HOME"
24
25 #else   /* assume WIN32 */
26 #include <windows.h>
27
28 #define DIR_SEP         '\\'
29 #define HOME_ENV        "USERPROFILE"
30
31 #endif  /* __unix__ */
32
33
34 #ifndef PREFIX
35 #define PREFIX  ""
36 #endif  /* PREFIX */
37
38 #define MAX_PATH        1024
39 #define CONF_ENV        "NLOC_CONFIG_PATH"
40 #define DATA_ENV        "NLOC_DATA_PATH"
41 #define LOC_FUNC_COUNT  2
42
43 typedef const char *(*loc_func_type)(const char*);
44
45 static const char *locate_config(const char *file);
46 static const char *locate_data(const char *file);
47 static const char *exec_path(void);
48
49 static char path[MAX_PATH];
50 static loc_func_type loc_func[LOC_FUNC_COUNT] = {locate_config, locate_data};
51
52 const char *loc_get_path(const char *file, enum loc_file_type file_type) {
53         if(file_type >= LOC_FUNC_COUNT) return 0;
54         return loc_func[file_type](file);
55 }
56
57 static const char *locate_config(const char *file) {
58         FILE *fp;
59         char *env, *pptr = path;
60         const char *ex_path, *fptr = file;
61         
62         /* first try $NLOC_CONFIG_PATH/file */
63         env = getenv(CONF_ENV);
64         if(env) {
65                 while(*env) *pptr++ = *env++;
66                 if(*(env - 1) != DIR_SEP) *pptr++ = DIR_SEP;
67                 while(*fptr) *pptr++ = *fptr++;
68                 *pptr++ = 0;
69                 
70                 fprintf(stderr, "trying: %s\n", path);
71                 if((fp = fopen(path, "r"))) {
72                         fclose(fp);
73                         return path;
74                 }
75         }
76
77         /* then try $HOME/.file */
78         pptr = path;
79         fptr = file;
80         env = getenv(HOME_ENV);
81         if(env) {
82                 while(*env) *pptr++ = *env++;
83                 if(*(env - 1) != DIR_SEP) *pptr++ = DIR_SEP;
84 #ifdef __unix__
85                 *pptr++ = '.';
86 #endif  /* __unix__ */
87                 while(*fptr) *pptr++ = *fptr++;
88                 *pptr++ = 0;
89
90                 fprintf(stderr, "trying: %s\n", path);
91                 if((fp = fopen(path, "r"))) {
92                         fclose(fp);
93                         return path;
94                 }
95         }
96
97 #ifdef __unix__
98         /* then PREFIX/etc/file */
99         strcpy(path, PREFIX);
100         strcat(path, "/etc/");
101         strcat(path, file);
102         
103         fprintf(stderr, "trying: %s\n", path);
104         if((fp = fopen(path, "r"))) {
105                 fclose(fp);
106                 return path;
107         }
108 #else
109         /* or something similar on win32 */
110         env = getenv("ALLUSERSPROFILE");
111         if(env) {
112                 strcpy(path, env);
113                 strcat(path, "\\");
114                 strcat(path, file);
115
116                 fprintf(stderr, "trying: %s\n", path);
117                 if((fp = fopen(path, "r"))) {
118                         fclose(fp);
119                         return path;
120                 }
121         }
122 #endif  /* __unix__ */
123
124
125         /* finally as a last resort try the executable directory, this may not work */
126         if((ex_path = exec_path())) {
127                 strcpy(path, ex_path);
128                 strcat(path, file);
129
130                 fprintf(stderr, "trying: %s\n", path);
131                 if((fp = fopen(path, "r"))) {
132                         fclose(fp);
133                         return path;
134                 }
135         }
136
137         return 0;
138 }
139
140 /* TODO: not implemented yet */
141 static const char *locate_data(const char *file) {
142         return 0;
143 }
144
145 static const char *exec_path(void) {
146         static char path[MAX_PATH];
147         int ccount = 0;
148         char *ptr;
149         
150 #ifdef __linux__
151         ccount = readlink("/proc/self/exe", path, MAX_PATH - 1);
152 #endif  /* __linux__ */
153
154 #ifdef __FreeBSD__
155         ccount = readlink("/proc/curproc/file", path, MAX_PATH - 1);
156 #endif  /* __FreeBSD__ */
157         
158 #ifdef WIN32
159         ccount = GetModuleFileName(0, path, MAX_PATH - 1);      
160 #endif  /* WIN32 */
161         
162         if(!ccount) return 0;
163         
164         path[ccount] = 0;
165         
166         ptr = strrchr(path, DIR_SEP);
167         if(!ptr) return 0;
168         
169         *(ptr + 1) = 0;
170
171         return path;
172 }