dynwatch

view locator.c @ 0:ce3c5e4c75bf

dynwatch DynDNS updater for windows
author John Tsiombikas <nuclear@siggraph.org>
date Wed, 18 May 2011 05:53:29 +0300
parents
children
line source
1 /*
2 This is a small cross-platform resource file locator library.
3 Author: John Tsiombikas <nuclear@siggraph.org> 2004
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 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include "locator.h"
14 #ifdef HAVE_CONFIG
15 #include "config.h"
16 #endif /* HAVE_CONFIG */
18 #ifdef __unix__
19 #define __USE_BSD /* to include readlink() prototype */
20 #include <unistd.h>
22 #define DIR_SEP '/'
23 #define HOME_ENV "HOME"
25 #else /* assume WIN32 */
26 #include <windows.h>
28 #define DIR_SEP '\\'
29 #define HOME_ENV "USERPROFILE"
31 #endif /* __unix__ */
34 #ifndef PREFIX
35 #define PREFIX ""
36 #endif /* PREFIX */
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
43 typedef const char *(*loc_func_type)(const char*);
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);
49 static char path[MAX_PATH];
50 static loc_func_type loc_func[LOC_FUNC_COUNT] = {locate_config, locate_data};
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 }
57 static const char *locate_config(const char *file) {
58 FILE *fp;
59 char *env, *pptr = path;
60 const char *fptr = file;
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;
70 fprintf(stderr, "trying: %s\n", path);
71 if((fp = fopen(path, "r"))) {
72 fclose(fp);
73 return path;
74 }
75 }
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;
90 fprintf(stderr, "trying: %s\n", path);
91 if((fp = fopen(path, "r"))) {
92 fclose(fp);
93 return path;
94 }
95 }
97 #ifdef __unix__
98 /* then PREFIX/etc/file */
99 strcpy(path, PREFIX);
100 strcat(path, "/etc/");
101 strcat(path, file);
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);
116 fprintf(stderr, "trying: %s\n", path);
117 if((fp = fopen(path, "r"))) {
118 fclose(fp);
119 return path;
120 }
121 }
122 #endif /* __unix__ */
125 /* finally as a last resort try the executable directory, this may not work */
126 strcpy(path, exec_path());
127 strcat(path, file);
129 fprintf(stderr, "trying: %s\n", path);
130 if((fp = fopen(path, "r"))) {
131 fclose(fp);
132 return path;
133 }
135 return 0;
136 }
138 /* TODO: not implemented yet */
139 static const char *locate_data(const char *file) {
140 return 0;
141 }
143 static const char *exec_path(void) {
144 static char path[MAX_PATH];
145 int ccount = 0;
146 char *ptr;
148 #ifdef __linux__
149 ccount = readlink("/proc/self/exe", path, MAX_PATH - 1);
150 #endif /* __linux__ */
152 #ifdef __FreeBSD__
153 ccount = readlink("/proc/curproc/file", path, MAX_PATH - 1);
154 #endif /* __FreeBSD__ */
156 #ifdef WIN32
157 ccount = GetModuleFileName(0, path, MAX_PATH - 1);
158 #endif /* WIN32 */
160 if(!ccount) return 0;
162 path[ccount] = 0;
164 ptr = strrchr(path, DIR_SEP);
165 if(!ptr) return 0;
167 *(ptr + 1) = 0;
169 return path;
170 }