1 |
|
|
2 |
/* config.c --- gereric config file loader |
/* config.c --- gereric config file loader |
3 |
Copyright (C) 1999 Beau Kuiper |
Copyright (C) 1999 Beau Kuiper |
4 |
|
|
17 |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
18 |
|
|
19 |
#include "ftpd.h" |
#include "ftpd.h" |
20 |
char *getconfigdata_r(CONFIGFILECACHE *cache, int section, char *cmd, |
char *getconfigdata_r(CONFIGFILECACHE * cache, |
21 |
int *occur, int depth, int *error); |
int section, |
22 |
|
char *cmd, |
23 |
|
int *occur, |
24 |
|
int depth, |
25 |
|
int *error); |
26 |
|
|
27 |
/* this, rather messyly, splits an input line into the command and data |
/* this, rather messyly, splits an input line into the command and data |
28 |
where the command is the first word on a line, and the data is the |
where the command is the first word on a line, and the data is the |
29 |
second. |
second. |
30 |
*/ |
*/ |
31 |
|
|
32 |
char *strsplit(char *in, char *cmd, char *data) |
char *strsplit(char *in, |
33 |
|
char *cmd, |
34 |
|
char *data) |
35 |
{ |
{ |
36 |
int pos = 0; |
int pos = 0; |
37 |
int pos2 = 0; |
int pos2 = 0; |
38 |
|
|
39 |
if (strlen(in) >= 1) |
if (strlen(in) >= 1) |
40 |
if (in[strlen(in) - 1] == 10) |
if (in[strlen(in) - 1] == 10) |
41 |
in[strlen(in) - 1] = 0; |
in[strlen(in) - 1] = 0; |
42 |
|
|
43 |
while(in[pos] != 0) /* scan entire string resolving \ and |
while (in[pos] != 0) /* scan entire string resolving \ and |
44 |
remove comments */ |
* remove comments */ |
45 |
{ |
{ |
46 |
if ((in[pos] == '\\') && (in[pos+1] != 0)) |
if ((in[pos] == '\\') && (in[pos + 1] != 0)) |
47 |
pos++; |
pos++; |
48 |
else if (in[pos] == '#') |
else if (in[pos] == '#') |
49 |
{ |
{ |
53 |
in[pos2] = in[pos]; |
in[pos2] = in[pos]; |
54 |
pos++; |
pos++; |
55 |
pos2++; |
pos2++; |
56 |
} |
} |
57 |
in[pos2] = 0; |
in[pos2] = 0; |
58 |
|
|
59 |
pos = 0; |
pos = 0; |
60 |
pos2 = 0; |
pos2 = 0; |
61 |
while((in[pos] <= 32) && (in[pos] != 0)) |
while ((in[pos] <= 32) && (in[pos] != 0)) |
62 |
pos++; |
pos++; |
63 |
if (in[pos] == 0) |
if (in[pos] == 0) |
64 |
return(NULL); |
return (NULL); |
65 |
|
|
66 |
while(((unsigned char)(in[pos]) > 32) && (in[pos] != 0)) |
while (((unsigned char) (in[pos]) > 32) && (in[pos] != 0)) |
67 |
{ |
{ |
68 |
cmd[pos2] = in[pos]; |
cmd[pos2] = in[pos]; |
69 |
pos2++; |
pos2++; |
70 |
pos++; |
pos++; |
71 |
} |
} |
72 |
|
|
73 |
if (in[pos] == 0) |
if (in[pos] == 0) |
74 |
return(NULL); |
return (NULL); |
75 |
|
|
76 |
cmd[pos2] = 0; |
cmd[pos2] = 0; |
77 |
|
|
78 |
while((in[pos] <= 32) && (in[pos] != 0)) |
while ((in[pos] <= 32) && (in[pos] != 0)) |
79 |
pos++; |
pos++; |
80 |
if (in[pos] == 0) |
if (in[pos] == 0) |
81 |
return(NULL); |
return (NULL); |
82 |
|
|
83 |
pos2 = 0; |
pos2 = 0; |
84 |
strcpy(data, in + pos); |
strcpy(data, in + pos); |
85 |
|
|
86 |
pos = strlen(data); |
pos = strlen(data); |
87 |
|
|
88 |
/* now trace back spaces and tabes at end of line */ |
/* |
89 |
while(data[--pos] <= 32); |
* now trace back spaces and tabes at end of line |
90 |
|
*/ |
91 |
|
while (data[--pos] <= 32); |
92 |
|
|
93 |
data[pos + 1] = 0; |
data[pos + 1] = 0; |
94 |
return(data); |
return (data); |
95 |
} |
} |
96 |
|
|
97 |
/* This will open and load each line in the specified config file (filename) |
/* This will open and load each line in the specified config file (filename) |
99 |
a handler you specify with a void pointer (to be used as the structure |
a handler you specify with a void pointer (to be used as the structure |
100 |
that the config file will load each item into) */ |
that the config file will load each item into) */ |
101 |
|
|
102 |
int loadconfigfile(char *filename, int (* confighandler)(char *, char *, int, void *), |
int loadconfigfile(char *filename, |
103 |
void *configdata, int besecure, int *handlererror, int *linenum) |
int (*confighandler) (char *, |
104 |
{ |
char *, |
105 |
|
int, |
106 |
|
void *), |
107 |
|
void *configdata, |
108 |
|
int besecure, |
109 |
|
int *handlererror, |
110 |
|
int *linenum) |
111 |
|
{ |
112 |
NEWFILE *configfile; |
NEWFILE *configfile; |
113 |
char *inputline; |
char *inputline; |
114 |
char *cmd = NULL; |
char *cmd = NULL; |
115 |
char *data = NULL; |
char *data = NULL; |
116 |
int result; |
int result; |
117 |
|
|
118 |
*linenum = 0; |
*linenum = 0; |
119 |
configfile = nfopen(filename); |
configfile = nfopen(filename); |
120 |
if (configfile == NULL) |
if (configfile == NULL) |
121 |
return(CONFIG_FILE_ERROR); |
return (CONFIG_FILE_ERROR); |
122 |
|
|
123 |
if (besecure) |
if (besecure) |
124 |
if (!isfilesafe(configfile->fd)) |
if (!isfilesafe(configfile->fd)) |
125 |
{ |
{ |
126 |
nfclose(configfile); |
nfclose(configfile); |
127 |
return(CONFIG_FILE_UNSAFE); |
return (CONFIG_FILE_UNSAFE); |
128 |
} |
} |
129 |
|
|
130 |
result = CONFIG_OK; |
result = CONFIG_OK; |
131 |
while((inputline = nfgetcs(configfile, '\n')) != NULL) |
while ((inputline = nfgetcs(configfile, '\n')) != NULL) |
132 |
{ |
{ |
133 |
int a = strlen(inputline) + 1; |
int a = strlen(inputline) + 1; |
134 |
reallocwrapper(a, (void **)&cmd); |
|
135 |
reallocwrapper(a, (void **)&data); |
reallocwrapper(a, (void **) &cmd); |
136 |
|
reallocwrapper(a, (void **) &data); |
137 |
(*linenum)++; |
(*linenum)++; |
138 |
|
|
139 |
/* This is a fix for config files written with DOS |
/* |
140 |
based software */ |
* This is a fix for config files written with DOS |
141 |
|
* based software |
142 |
|
*/ |
143 |
|
|
144 |
a = strlen(inputline); |
a = strlen(inputline); |
145 |
if (a >= 2) |
if (a >= 2) |
146 |
if (inputline[a-2] == '\r') |
if (inputline[a - 2] == '\r') |
147 |
inputline[a-2] = 0; |
inputline[a - 2] = 0; |
148 |
|
|
149 |
if (strsplit(inputline, cmd, data) != NULL) |
if (strsplit(inputline, cmd, data) != NULL) |
150 |
{ |
{ |
151 |
*handlererror = confighandler(cmd, data, *linenum, configdata); |
*handlererror = confighandler(cmd, data, *linenum, configdata); |
158 |
} |
} |
159 |
freewrapper(inputline); |
freewrapper(inputline); |
160 |
} |
} |
161 |
|
|
162 |
freeifnotnull(cmd); |
freeifnotnull(cmd); |
163 |
freeifnotnull(data); |
freeifnotnull(data); |
164 |
nfclose(configfile); |
nfclose(configfile); |
165 |
return(result); |
return (result); |
166 |
} |
} |
167 |
|
|
168 |
/* this code is quite tricky, but it saves much memory */ |
/* this code is quite tricky, but it saves much memory */ |
169 |
|
|
170 |
int cachemaker(char *cmd, char *data, int linenum, void *c) |
int cachemaker(char *cmd, |
171 |
|
char *data, |
172 |
|
int linenum, |
173 |
|
void *c) |
174 |
{ |
{ |
175 |
char newcmd[32]; |
char newcmd[32]; |
176 |
CONFIGFILECACHE *cache = (CONFIGFILECACHE *)c; |
CONFIGFILECACHE *cache = (CONFIGFILECACHE *) c; |
177 |
int count; |
int count; |
178 |
|
|
179 |
if (strcasecmp(cmd, "[section]") == 0) |
if (strcasecmp(cmd, "[section]") == 0) |
180 |
{ |
{ |
181 |
/* add new section */ |
/* |
182 |
|
* add new section |
183 |
|
*/ |
184 |
|
|
185 |
if (strcasecmp(data, "none") == 0) |
if (strcasecmp(data, "none") == 0) |
186 |
return(CFC_SECTION_NONE); |
return (CFC_SECTION_NONE); |
187 |
|
|
188 |
/* check to see if section already is there */ |
/* |
189 |
|
* check to see if section already is there |
190 |
|
*/ |
191 |
for (count = 0; count < cache->sectioncount; count++) |
for (count = 0; count < cache->sectioncount; count++) |
192 |
if (strcasecmp(data, cache->sectionlist + cache->sectionindex[count]) == 0) |
if (strcasecmp |
193 |
return(CFC_SECTION_EXISTS); |
(data, cache->sectionlist + cache->sectionindex[count]) == 0) |
194 |
|
return (CFC_SECTION_EXISTS); |
195 |
/* nupe, add it, may be a little slow, but is efficient enough */ |
|
196 |
|
/* |
197 |
|
* nupe, add it, may be a little slow, but is efficient enough |
198 |
|
*/ |
199 |
cache->sectioncount++; |
cache->sectioncount++; |
200 |
reallocwrapper(sizeof(int) * cache->sectioncount, (void *)&cache->sectionindex); |
reallocwrapper(sizeof(int) * cache->sectioncount, |
201 |
reallocwrapper(sizeof(int) * cache->sectioncount, (void *)&cache->sectionlinenum); |
(void *) &cache->sectionindex); |
202 |
|
reallocwrapper(sizeof(int) * cache->sectioncount, |
203 |
|
(void *) &cache->sectionlinenum); |
204 |
cache->sectionindex[cache->sectioncount - 1] = cache->sectionlen; |
cache->sectionindex[cache->sectioncount - 1] = cache->sectionlen; |
205 |
cache->sectionlinenum[cache->sectioncount - 1] = linenum; |
cache->sectionlinenum[cache->sectioncount - 1] = linenum; |
206 |
|
|
207 |
cache->sectionlen += strlen(data) + 1; |
cache->sectionlen += strlen(data) + 1; |
208 |
reallocwrapper(cache->sectionlen, (void *)&(cache->sectionlist)); |
reallocwrapper(cache->sectionlen, (void *) &(cache->sectionlist)); |
209 |
strcpy(cache->sectionlist + cache->sectionindex[cache->sectioncount - 1], data); |
strcpy(cache->sectionlist + |
210 |
|
cache->sectionindex[cache->sectioncount - 1], data); |
211 |
reallocwrapper(sizeof(int) * cache->sectioncount, (void **)&(cache->index)); |
|
212 |
|
reallocwrapper(sizeof(int) * cache->sectioncount, |
213 |
|
(void **) &(cache->index)); |
214 |
cache->index[cache->sectioncount - 1] = cache->datacount; |
cache->index[cache->sectioncount - 1] = cache->datacount; |
215 |
} |
} |
216 |
else |
else |
217 |
{ |
{ |
218 |
if (cache->sectioncount == 0) |
if (cache->sectioncount == 0) |
219 |
return(CFC_NO_SECTION); |
return (CFC_NO_SECTION); |
220 |
|
|
221 |
/* change an include to a special character for quick |
/* |
222 |
recognision. Puts this special character in a new |
* change an include to a special character for quick |
223 |
string that is long enough for the machine type |
* recognision. Puts this special character in a new |
224 |
muddleftpd is running on */ |
* string that is long enough for the machine type |
225 |
|
* muddleftpd is running on |
226 |
|
*/ |
227 |
|
|
228 |
if (strcasecmp(cmd, "include") == 0) |
if (strcasecmp(cmd, "include") == 0) |
229 |
{ |
{ |
230 |
memset(newcmd, 1, sizeof(int) + 2); |
memset(newcmd, 1, sizeof(int) + 2); |
231 |
newcmd[sizeof(int)+1] = 0; |
newcmd[sizeof(int) + 1] = 0; |
232 |
cmd = newcmd; |
cmd = newcmd; |
233 |
} |
} |
234 |
/* add it to the data list */ |
/* |
235 |
|
* add it to the data list |
236 |
cache->datacount++; |
*/ |
237 |
reallocwrapper(sizeof(char *) * cache->datacount, (void *)&(cache->dataindex)); |
|
238 |
reallocwrapper(sizeof(char *) * cache->datacount, (void *)&(cache->cmdindex)); |
cache->datacount++; |
239 |
reallocwrapper(sizeof(int) * cache->datacount, (void *)&cache->datalinenum); |
reallocwrapper(sizeof(char *) * cache->datacount, |
240 |
|
(void *) &(cache->dataindex)); |
241 |
|
reallocwrapper(sizeof(char *) * cache->datacount, |
242 |
|
(void *) &(cache->cmdindex)); |
243 |
|
reallocwrapper(sizeof(int) * cache->datacount, |
244 |
|
(void *) &cache->datalinenum); |
245 |
|
|
246 |
cache->dataindex[cache->datacount - 1] = cache->datalen; |
cache->dataindex[cache->datacount - 1] = cache->datalen; |
247 |
cache->cmdindex[cache->datacount - 1] = cache->cmdlen; |
cache->cmdindex[cache->datacount - 1] = cache->cmdlen; |
248 |
cache->datalinenum[cache->datacount - 1] = linenum; |
cache->datalinenum[cache->datacount - 1] = linenum; |
249 |
|
|
250 |
cache->datalen += strlen(data) + 1; |
cache->datalen += strlen(data) + 1; |
251 |
cache->cmdlen += strlen(cmd) + 1; |
cache->cmdlen += strlen(cmd) + 1; |
252 |
|
|
253 |
reallocwrapper(cache->datalen, (void *)&(cache->datalist)); |
reallocwrapper(cache->datalen, (void *) &(cache->datalist)); |
254 |
reallocwrapper(cache->cmdlen, (void *)&(cache->cmdlist)); |
reallocwrapper(cache->cmdlen, (void *) &(cache->cmdlist)); |
255 |
|
|
256 |
strcpy(cache->datalist + cache->dataindex[cache->datacount - 1], data); |
strcpy(cache->datalist + cache->dataindex[cache->datacount - 1], |
257 |
|
data); |
258 |
strcpy(cache->cmdlist + cache->cmdindex[cache->datacount - 1], cmd); |
strcpy(cache->cmdlist + cache->cmdindex[cache->datacount - 1], cmd); |
259 |
} |
} |
260 |
return(FALSE); |
return (FALSE); |
261 |
} |
} |
262 |
|
|
263 |
CONFIGFILECACHE *loadconfigcache(char *filename, int *linenum, int *error) |
CONFIGFILECACHE *loadconfigcache(char *filename, |
264 |
|
int *linenum, |
265 |
|
int *error) |
266 |
{ |
{ |
267 |
CONFIGFILECACHE *newcache = NULL; |
CONFIGFILECACHE *newcache = NULL; |
268 |
int result, count; |
int result, count; |
269 |
|
|
270 |
newcache = mallocwrapper(sizeof(CONFIGFILECACHE)); |
newcache = mallocwrapper(sizeof(CONFIGFILECACHE)); |
271 |
newcache->sectioncount = 0; |
newcache->sectioncount = 0; |
272 |
newcache->datacount = 0; |
newcache->datacount = 0; |
282 |
newcache->index = NULL; |
newcache->index = NULL; |
283 |
newcache->sectionlinenum = NULL; |
newcache->sectionlinenum = NULL; |
284 |
newcache->datalinenum = NULL; |
newcache->datalinenum = NULL; |
285 |
|
|
286 |
result = loadconfigfile(filename, cachemaker, newcache, TRUE, error, linenum); |
result = |
287 |
|
loadconfigfile(filename, cachemaker, newcache, TRUE, error, linenum); |
288 |
|
|
289 |
if (result != CONFIG_OK) |
if (result != CONFIG_OK) |
290 |
{ |
{ |
291 |
if (result != CONFIG_HANDLER_ERROR) |
if (result != CONFIG_HANDLER_ERROR) |
292 |
*error = result; |
*error = result; |
293 |
freeconfigcache(newcache); |
freeconfigcache(newcache); |
294 |
return(NULL); |
return (NULL); |
295 |
} |
} |
296 |
|
|
297 |
/* resolve all include references! */ |
/* |
298 |
|
* resolve all include references! |
299 |
|
*/ |
300 |
|
|
301 |
for (count = 0; count < newcache->datacount; count++) |
for (count = 0; count < newcache->datacount; count++) |
302 |
{ |
{ |
303 |
if (*(newcache->cmdlist + newcache->cmdindex[count]) == 1) |
if (*(newcache->cmdlist + newcache->cmdindex[count]) == 1) |
304 |
{ |
{ |
305 |
/* found an include item, resolve the include reference */ |
/* |
306 |
int section = getsectionid(newcache, newcache->datalist + newcache->dataindex[count]); |
* found an include item, resolve the include reference |
307 |
|
*/ |
308 |
|
int section = getsectionid(newcache, |
309 |
|
newcache->datalist + |
310 |
|
newcache->dataindex[count]); |
311 |
if (section == -1) |
if (section == -1) |
312 |
{ |
{ |
313 |
*error = CFC_INCLUDE_ERROR; |
*error = CFC_INCLUDE_ERROR; |
314 |
*linenum = newcache->datalinenum[count]; |
*linenum = newcache->datalinenum[count]; |
315 |
freeconfigcache(newcache); |
freeconfigcache(newcache); |
316 |
return(NULL); |
return (NULL); |
317 |
} |
} |
318 |
memcpy((char *)(newcache->cmdlist + newcache->cmdindex[count] + 1), §ion, sizeof(section)); |
memcpy((char *) (newcache->cmdlist + newcache->cmdindex[count] + |
319 |
|
1), §ion, sizeof(section)); |
320 |
} |
} |
321 |
} |
} |
322 |
|
|
323 |
/* check for recursive includes! */ |
/* |
324 |
|
* check for recursive includes! |
325 |
|
*/ |
326 |
for (count = 0; count < newcache->sectioncount; count++) |
for (count = 0; count < newcache->sectioncount; count++) |
327 |
{ |
{ |
328 |
int deptherror = FALSE; |
int deptherror = FALSE; |
329 |
int occur = 1; |
int occur = 1; |
330 |
char *data; |
char *data; |
331 |
|
|
332 |
/* search for something to check for looping */ |
/* |
333 |
data = getconfigdata_r(newcache, count, "[section]", &occur, 1, &deptherror); |
* search for something to check for looping |
334 |
|
*/ |
335 |
|
data = |
336 |
|
getconfigdata_r(newcache, count, "[section]", &occur, 1, |
337 |
|
&deptherror); |
338 |
if (deptherror) |
if (deptherror) |
339 |
{ |
{ |
340 |
*error = CFC_INCLUDE_LOOP; |
*error = CFC_INCLUDE_LOOP; |
341 |
*linenum = newcache->sectionlinenum[count]; |
*linenum = newcache->sectionlinenum[count]; |
342 |
freeconfigcache(newcache); |
freeconfigcache(newcache); |
343 |
return(NULL); |
return (NULL); |
344 |
} |
} |
345 |
} |
} |
346 |
freeifnotnull(newcache->sectionlinenum); |
freeifnotnull(newcache->sectionlinenum); |
347 |
newcache->sectionlinenum = NULL; |
newcache->sectionlinenum = NULL; |
348 |
freeifnotnull(newcache->datalinenum); |
freeifnotnull(newcache->datalinenum); |
349 |
newcache->datalinenum = NULL; |
newcache->datalinenum = NULL; |
350 |
return(newcache); |
return (newcache); |
351 |
} |
} |
352 |
|
|
353 |
char *config_errorstr(int result) |
char *config_errorstr(int result) |
354 |
{ |
{ |
355 |
static char longerror[256]; |
static char longerror[256]; |
356 |
|
|
357 |
switch(result) |
switch (result) |
358 |
{ |
{ |
359 |
case CONFIG_OK: |
case CONFIG_OK: |
360 |
return("No errors."); |
return ("No errors."); |
361 |
case CONFIG_HANDLER_ERROR: |
case CONFIG_HANDLER_ERROR: |
362 |
return("Config handler returned error result."); |
return ("Config handler returned error result."); |
363 |
case CONFIG_FILE_UNSAFE: |
case CONFIG_FILE_UNSAFE: |
364 |
return("File was not deemed safe. Must not be group/world writable and must be owned by process owner."); |
return |
365 |
case CONFIG_FILE_ERROR: |
("File was not deemed safe. Must not be group/world writable and must be owned by process owner."); |
366 |
snprintf(longerror, 256, "Error opening file (%s).", strerror(errno)); |
case CONFIG_FILE_ERROR: |
367 |
return(longerror); |
snprintf(longerror, 256, "Error opening file (%s).", strerror(errno)); |
368 |
case CFC_INCLUDE_ERROR: |
return (longerror); |
369 |
return("Included section could not be found."); |
case CFC_INCLUDE_ERROR: |
370 |
case CFC_SECTION_NONE: |
return ("Included section could not be found."); |
371 |
return("Section cannot be named 'none'."); |
case CFC_SECTION_NONE: |
372 |
case CFC_SECTION_EXISTS: |
return ("Section cannot be named 'none'."); |
373 |
return("Section already exists."); |
case CFC_SECTION_EXISTS: |
374 |
case CFC_NO_SECTION: |
return ("Section already exists."); |
375 |
return("No section has been decleared for config data."); |
case CFC_NO_SECTION: |
376 |
case CFC_INCLUDE_LOOP: |
return ("No section has been decleared for config data."); |
377 |
return("A possible recursive loop was found in section."); |
case CFC_INCLUDE_LOOP: |
378 |
default: |
return ("A possible recursive loop was found in section."); |
379 |
return("Unknown error!"); |
default: |
380 |
|
return ("Unknown error!"); |
381 |
} |
} |
382 |
} |
} |
383 |
|
|
384 |
int getsectionid(CONFIGFILECACHE *cache, char *section) |
int getsectionid(CONFIGFILECACHE * cache, |
385 |
|
char *section) |
386 |
{ |
{ |
387 |
int count; |
int count; |
388 |
|
|
389 |
for(count = 0; count < cache->sectioncount; count++) |
for (count = 0; count < cache->sectioncount; count++) |
390 |
if (strcasecmp(section, cache->sectionlist + cache->sectionindex[count]) == 0) |
if (strcasecmp |
391 |
return(count); |
(section, cache->sectionlist + cache->sectionindex[count]) == 0) |
392 |
|
return (count); |
393 |
return(-1); |
|
394 |
|
return (-1); |
395 |
} |
} |
396 |
|
|
397 |
char *getconfigdata_r(CONFIGFILECACHE *cache, int section, char *cmd, int *occur, int depth, int *error) |
char *getconfigdata_r(CONFIGFILECACHE * cache, |
398 |
|
int section, |
399 |
|
char *cmd, |
400 |
|
int *occur, |
401 |
|
int depth, |
402 |
|
int *error) |
403 |
{ |
{ |
404 |
int count, last; |
int count, last; |
405 |
int first; |
int first; |
409 |
assert(section < cache->sectioncount); |
assert(section < cache->sectioncount); |
410 |
assert(section >= 0); |
assert(section >= 0); |
411 |
assert(*occur > 0); |
assert(*occur > 0); |
412 |
|
|
413 |
if (depth > MAXINCLUDEDEPTH) |
if (depth > MAXINCLUDEDEPTH) |
414 |
{ |
{ |
415 |
*error = TRUE; |
*error = TRUE; |
416 |
return(NULL); |
return (NULL); |
417 |
} |
} |
418 |
|
|
419 |
first = cache->index[section]; |
first = cache->index[section]; |
420 |
|
|
421 |
/* find the last datalist element to look at */ |
/* |
422 |
|
* find the last datalist element to look at |
423 |
|
*/ |
424 |
if (section == cache->sectioncount - 1) |
if (section == cache->sectioncount - 1) |
425 |
last = cache->datacount; |
last = cache->datacount; |
426 |
else |
else |
427 |
last = cache->index[section + 1]; |
last = cache->index[section + 1]; |
428 |
|
|
429 |
/* find the occurance wanted */ |
/* |
430 |
for(count = first; count < last; count++) |
* find the occurance wanted |
431 |
|
*/ |
432 |
|
for (count = first; count < last; count++) |
433 |
{ |
{ |
434 |
if (*(cache->cmdlist + cache->cmdindex[count]) == 1) |
if (*(cache->cmdlist + cache->cmdindex[count]) == 1) |
435 |
{ |
{ |
436 |
memcpy(&num, (char *)(cache->cmdlist + cache->cmdindex[count] + 1), sizeof(num)); |
memcpy(&num, |
437 |
res = getconfigdata_r(cache, num, cmd, |
(char *) (cache->cmdlist + cache->cmdindex[count] + 1), |
438 |
occur, depth + 1, error); |
sizeof(num)); |
439 |
|
res = getconfigdata_r(cache, num, cmd, occur, depth + 1, error); |
440 |
if (res) |
if (res) |
441 |
return(res); |
return (res); |
442 |
} |
} |
443 |
|
|
444 |
if (strcasecmp(cmd, cache->cmdlist + cache->cmdindex[count]) == 0) |
if (strcasecmp(cmd, cache->cmdlist + cache->cmdindex[count]) == 0) |
445 |
(*occur)--; |
(*occur)--; |
446 |
|
|
447 |
if (*occur == 0) |
if (*occur == 0) |
448 |
return(cache->datalist + cache->dataindex[count]); |
return (cache->datalist + cache->dataindex[count]); |
449 |
} |
} |
450 |
|
|
451 |
/* if not found, return NULL */ |
/* |
452 |
return(NULL); |
* if not found, return NULL |
453 |
|
*/ |
454 |
|
return (NULL); |
455 |
} |
} |
456 |
|
|
457 |
char *getconfigdata(CONFIGFILECACHE *cache, int section, char *cmd, int occur) |
char *getconfigdata(CONFIGFILECACHE * cache, |
458 |
|
int section, |
459 |
|
char *cmd, |
460 |
|
int occur) |
461 |
{ |
{ |
462 |
int error; |
int error; |
463 |
return(getconfigdata_r(cache, section, cmd, &occur, 1, &error)); |
|
464 |
|
return (getconfigdata_r(cache, section, cmd, &occur, 1, &error)); |
465 |
} |
} |
466 |
|
|
467 |
char **makeconfiglist(CONFIGFILECACHE *cache, char *section, char *label) |
char **makeconfiglist(CONFIGFILECACHE * cache, |
468 |
|
char *section, |
469 |
|
char *label) |
470 |
{ |
{ |
471 |
int sectnum; |
int sectnum; |
472 |
char **out; |
char **out; |
473 |
char *setting; |
char *setting; |
474 |
int occur; |
int occur; |
475 |
|
|
476 |
sectnum = getsectionid(cache, section); |
sectnum = getsectionid(cache, section); |
477 |
if (sectnum == -1) |
if (sectnum == -1) |
478 |
return(NULL); |
return (NULL); |
479 |
|
|
480 |
out = mallocwrapper(sizeof(char *)); |
out = mallocwrapper(sizeof(char *)); |
481 |
occur = 1; |
occur = 1; |
482 |
|
|
483 |
while ((setting = getconfigdata(cache, sectnum, label, occur))) |
while ((setting = getconfigdata(cache, sectnum, label, occur))) |
484 |
{ |
{ |
485 |
out[occur - 1] = setting; |
out[occur - 1] = setting; |
486 |
occur++; |
occur++; |
487 |
reallocwrapper(sizeof(char *) * occur, (void *)&out); |
reallocwrapper(sizeof(char *) * occur, (void *) &out); |
488 |
} |
} |
489 |
out[occur - 1] = NULL; |
out[occur - 1] = NULL; |
490 |
return(out); |
return (out); |
491 |
} |
} |
492 |
|
|
493 |
void loadintfromconfig(CONFIGFILECACHE *cache, int section, char *setting, |
void loadintfromconfig(CONFIGFILECACHE * cache, |
494 |
int *to, int def) |
int section, |
495 |
|
char *setting, |
496 |
|
int *to, |
497 |
|
int def) |
498 |
{ |
{ |
499 |
char *set = getconfigdata(cache, section, setting, 1); |
char *set = getconfigdata(cache, section, setting, 1); |
500 |
|
|
501 |
if (set) |
if (set) |
502 |
sscanf(set, "%d", to); |
sscanf(set, "%d", to); |
503 |
else |
else |
504 |
*to = def; |
*to = def; |
505 |
} |
} |
506 |
|
|
507 |
void loadstrfromconfig(CONFIGFILECACHE *cache, int section, char *setting, |
void loadstrfromconfig(CONFIGFILECACHE * cache, |
508 |
char **to, char *def) |
int section, |
509 |
|
char *setting, |
510 |
|
char **to, |
511 |
|
char *def) |
512 |
{ |
{ |
513 |
char *set = getconfigdata(cache, section, setting, 1); |
char *set = getconfigdata(cache, section, setting, 1); |
514 |
|
|
515 |
if (set) |
if (set) |
516 |
*to = set; |
*to = set; |
517 |
else |
else |
518 |
*to = def; |
*to = def; |
519 |
} |
} |
520 |
|
|
521 |
void freeconfigcache(CONFIGFILECACHE *cache) |
void freeconfigcache(CONFIGFILECACHE * cache) |
522 |
{ |
{ |
523 |
freeifnotnull(cache->sectionindex); |
freeifnotnull(cache->sectionindex); |
524 |
freeifnotnull(cache->dataindex); |
freeifnotnull(cache->dataindex); |
525 |
freeifnotnull(cache->cmdindex); |
freeifnotnull(cache->cmdindex); |
526 |
|
|
527 |
freeifnotnull(cache->sectionlist); |
freeifnotnull(cache->sectionlist); |
528 |
freeifnotnull(cache->index); |
freeifnotnull(cache->index); |
529 |
freeifnotnull(cache->datalist); |
freeifnotnull(cache->datalist); |